package com.itheima.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.common.R;
import com.itheima.dto.DishDto;
import com.itheima.entity.Category;
import com.itheima.entity.Dish;
import com.itheima.entity.DishFlavor;
import com.itheima.service.CategoryService;
import com.itheima.service.DishFlavorService;
import com.itheima.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/dish")
@Slf4j
public class DishController {
    @Autowired
    public DishService dishService;
    @Autowired
    public DishFlavorService dishFlavorService;
    //使用分类ID通过分类表查找分类名字
    @Autowired
    public CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 菜品信息分页查询
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    //获得分类名称：其实在这一章大家可以直接把Service层和mapper层写个DishDto那两个不用写了，这样的话老师刚才的代码就可以运行
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize,String name){
        //构造分页构造器对象
        Page<Dish> page1=new Page(page,pageSize);
        Page<DishDto> dtoPage=new Page<>();

        //要按顺序展示，故而需要进行条件查询
        LambdaQueryWrapper<Dish> lqw=new LambdaQueryWrapper<>();
        lqw.like(name!=null,Dish::getName,name);
        //添加排序条件，根据sort字段排序（注意是字段）
        lqw.orderByDesc(Dish::getUpdateTime);
        dishService.page(page1,lqw);

        //对象拷贝
        //提示：这里拷贝的是分页信息，并非实体类属性！
        //把菜品的分页信息（除了数据）复制给dto(因为dto要额外对数据处理)
        BeanUtils.copyProperties(page1,dtoPage,"records");

        List<Dish> records=page1.getRecords();
        List<DishDto> list=records.stream().map((item)->{
            //创建dto对象，赋分类名值
            DishDto dishDto = new DishDto();
            //由于创建的dishdto中的dish的属性为空，故而需要拷贝records子项目的数据
            BeanUtils.copyProperties(item,dishDto);

            //拿到菜品对应的ID
            Long categoryId = item.getCategoryId();
            //获取分类名
            Category category = categoryService.getById(categoryId);
            if(category != null) {
                String categoryName = category.getName();

                dishDto.setCategoryName(categoryName);
            }
            return dishDto;
        }).collect(Collectors.toList());
        //将处理后的数据传给页面，并传输修改后的页面信息给前端
        dtoPage.setRecords(list);
        return R.success(dtoPage);
    }

    //传参需要两个表的数据：多表连接
    //+封装一个DTO数据接收实体类,加上flavors字段，在继承dish类
    //Vo一般是后端封装给前端,Dto是接收从前端的数据
    /**
     * 新增菜品
     * @param dishDto
     * @return
     */

    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto) {
        log.info(dishDto.toString());
        dishService.saveWithFlavor(dishDto);
        //清理所有菜品的缓存数据
        //Set keys = redisTemplate.keys("dish_*");
        //redisTemplate.delete(keys);

        //清理某个分类下面的菜品缓存数据
        String key="dish_"+dishDto.getCategoryId()+"_"+dishDto.getStatus();
        redisTemplate.delete(key);
        return R.success("新增菜品成功！");
    }

    /**
     * 根据id查询菜品信息和对应的口味信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<DishDto> get(@PathVariable Long id){

        DishDto dishDto = dishService.getByIdWithFlavor(id);

        return R.success(dishDto);
    }

    /**
     * 修改菜品
     * @param dishDto
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody DishDto dishDto){
        log.info(dishDto.toString());
        dishService.updateWithFlavor(dishDto);
        //清理所有菜品的缓存数据
        //Set keys = redisTemplate.keys("dish_*");
        //redisTemplate.delete(keys);

        //清理某个分类下面的菜品缓存数据
        String key="dish_"+dishDto.getCategoryId()+"_"+dishDto.getStatus();
        redisTemplate.delete(key);
        return R.success("新增菜品成功");
    }

    /**
     * 修改销售状态（用于停售、起售按钮和批量停售、起售按钮）
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    public R<String> updateStatus(@PathVariable Integer status,Long[] ids){
        for (int i = 0; i < ids.length; i++) {
        LambdaQueryWrapper<Dish> lqw=new LambdaQueryWrapper<>();
        lqw.eq(Dish::getId,ids[i]);
        Dish one = dishService.getOne(lqw);
        one.setStatus(status);
        dishService.updateById(one);
        }
        return R.success("状态修改成功！");
    }

    /**
     * 删除菜品（用于删除按钮和批量删除按钮）
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> delete(Long[] ids){
        for (int i = 0; i < ids.length; i++) {
            dishService.deleteWithFlavor(ids[i]);
        }

        return R.success("菜品删除成功！");
    }


    /**
     * 根据条件查询对应的菜品数据
     * @param dish
     * @return
     */
    //参数为Long categoryId也可以，但为了传过来其他的也可以接受
    //当前端传来的值，不是个完整的对象，只是包含了 Req 中的部分参数时，不需要@RequestBody  当前端传来的是一个完成对象的时候，需要@RequestBody
  /*  @GetMapping("/list")
    public R<List<Dish>> list(Dish dish){
        LambdaQueryWrapper<Dish> lqw=new LambdaQueryWrapper<>();
        lqw.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        //添加条件，查询状态为1（起售状态）的菜品
        lqw.eq(Dish::getStatus,1);
        //添加排序条件,优先使用顺序排序，顺序相同就用更新时间排序
        lqw.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(lqw);

        return R.success(list);
    }*/

    /**
     * 根据条件查询对应的菜品数据
     * @param dish
     * @return
     */
    //参数为Long categoryId也可以，但为了传过来其他的也可以接受
    //当前端传来的值，不是个完整的对象，只是包含了 Req 中的部分参数时，不需要@RequestBody  当前端传来的是一个完成对象的时候，需要@RequestBody
    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){
        //http://localhost:8080/dish/list?categoryId=1397844263642378242&status=1
        //拼接key
        String key="dish_"+dish.getCategoryId()+"_"+dish.getStatus();

        //先从Redis中获取缓存菜品数据,希望缓存得到的数据类型是List<DishDto>
        List<DishDto> dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);

        //数据存在直接返回，无需查询数据库
        if (dishDtoList!=null){
            return R.success(dishDtoList);
        }

        //如果不存在，需要查询数据库，将查询到的菜品数据缓存到Redis
        LambdaQueryWrapper<Dish> lqw=new LambdaQueryWrapper<>();
        lqw.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        //添加条件，查询状态为1（起售状态）的菜品
        lqw.eq(Dish::getStatus,1);
        //添加排序条件,优先使用顺序排序，顺序相同就用更新时间排序
        lqw.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(lqw);

        // List<DishDto> dishDtoList=list.stream().map((item)->{
        dishDtoList=list.stream().map((item)->{
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);
            //菜品ID
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> qw = new LambdaQueryWrapper<>();
            qw.eq(DishFlavor::getDishId,dishId);
            //得到口味集合
            List<DishFlavor> dishFlavorList = dishFlavorService.list(qw);
            dishDto.setFlavors(dishFlavorList);
            return dishDto;
        }).collect(Collectors.toList());

        //查询数据库完成之后，存入Redis,保存时间一个钟
        //把list对象转为string类型
        redisTemplate.opsForValue().set(key, JSON.toJSONString(dishDtoList),60, TimeUnit.MINUTES);
        return R.success(dishDtoList);
    }
}
